package com.demo.test.leak

import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.TextView
import com.fortest.R
import com.demo.app.ApplicationLeakTest

/**
泄露方式：Application
泄露原因：Application的生命周期显然与应用的生命周期一致。
在Activity中把一个view放到Application的List中，使得这个view会一直被Application长期持有，
因此即使Activity已经退出了，Activity仍然被Application所引用着，得不到释放。

泄露报告　－－　LeakCanary：
23637 bytes retained by leaking objects
Signature: 5d7d85271dba53a3ed27ea87d5a7229db83e6
┬───
│ GC Root: System class
│
├─ android.app.Application class
│    Leaking: NO (ApplicationStrictMode↓ is not leaking and a class is never leaking)
│    ↓ static Application.mApplicationInstance
├─ com.demo.app.ApplicationStrictMode instance
│    Leaking: NO (Application is a singleton)
│    ApplicationStrictMode does not wrap an activity context
│    ↓ ApplicationStrictMode.leakedViews
│                            ~~~~~~~~~~~
├─ java.util.ArrayList instance
│    Leaking: UNKNOWN
│    ↓ ArrayList.elementData
│                ~~~~~~~~~~~
├─ java.lang.Object[] array
│    Leaking: UNKNOWN
│    ↓ Object[].[0]
│               ~~~
├─ android.widget.TextView instance
│    Leaking: YES (View.mContext references a destroyed activity)
│    mContext instance of com.demo.test.leak.ActivityLeakF_Application with mDestroyed = true
│    View#mParent is set
│    View#mAttachInfo is null (view detached)
│    View.mID = R.id.helper_text
│    View.mWindowAttachCount = 1
│    ↓ TextView.mContext
╰→ com.demo.test.leak.ActivityLeakF_Application instance
​     Leaking: YES (ObjectWatcher was watching this because com.demo.test.leak.ActivityLeakF_Application received Activity#onDestroy() callback and Activity#mDestroyed is true)
​     key = abd0770f-1724-4508-b89e-75b0b5d7aa12
​     watchDurationMillis = 5156
​     retainedDurationMillis = 156
 **/
class ActivityLeakF_Application : Activity() {
    val TAG = "LeakF_Application"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_leak_common)
        val textView = findViewById<TextView>(R.id.helper_text)
        textView.text = "泄露方式：Application\n" +
                "泄露原因：Application的生命周期显然与应用的生命周期一致。\n" +
                "在Activity中把一个view放到Application的List中，使得这个view会一直被Application长期持有，\n" +
                "因此即使Activity已经退出了，Activity仍然被Application所引用着，得不到释放。"

        val app = application as ApplicationLeakTest
        val leakedView = findViewById<View>(R.id.helper_text)
        Log.d(TAG, "Application引用view，导致内存泄露")
        // Leak from application class
        app.leakedViews.add(leakedView)

    }
}
